package com.sc.nft.admin.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.admin.request.*;
import com.sc.nft.annotation.SysMemberLogin;
import com.sc.nft.dao.DigitalCollectionDao;
import com.sc.nft.dao.PrivilegeDao;
import com.sc.nft.dao.UserCollectionChainLogDao;
import com.sc.nft.dto.AddDigitalCollectionDTO;
import com.sc.nft.dto.DigitalCollectionMarketTypeDTO;
import com.sc.nft.dto.UpdateDigitalCollectionDTO;
import com.sc.nft.entity.DigitalCollection;
import com.sc.nft.entity.Privilege;
import com.sc.nft.entity.UserCreatorInfo;
import com.sc.nft.entity.dto.AccessToCopyrightCollectioDTO;
import com.sc.nft.entity.dto.AdminPageFreeMarketCollectionDTO;
import com.sc.nft.entity.dto.CollectionListAccordingDaoDTO;
import com.sc.nft.entity.dto.CollectionSimpleDTO;
import com.sc.nft.entity.dto.chain.TransferLogDTO;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.CollectionChainStatusEnum;
import com.sc.nft.enums.CollectionLevel;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/Collection")
@Api(tags = "后台藏品模块")
public class DigitalCollectionAdminController {

    private final DigitalCollectionService digitalCollectionService;
    private final CatenaInfoService catenaInfoService;
    private final UserCreatorInfoService userCreatorInfoService;
    private final PrivilegeDao privilegeDao;
    private final PrivilegeService privilegeService;
    private final ShowLevelService showLevelService;
    private final DigitalCollectionDao digitalCollectionDao;
    private final UserCollectionChainLogDao userCollectionChainLogDao;
    private final Redisson redisson;


    @PostMapping(value = "/addCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "添加藏品", notes = "添加藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result addCollection(@Valid @RequestBody AddDigitalCollectionDTO addDigitalCollectionDTO) {
        addDigitalCollectionDTO.checkCirculationType();
        addDigitalCollectionDTO.checkConsumeCost();
        digitalCollectionService.addCollection(addDigitalCollectionDTO);
        return Result.success();
    }

    @PostMapping(value = "/editCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "编辑藏品", notes = "编辑藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result editCollection(@Valid @RequestBody UpdateDigitalCollectionDTO updateDigitalCollectionDTO) {
        updateDigitalCollectionDTO.checkConsumeCost();
        digitalCollectionService.updateDigitalCollection(updateDigitalCollectionDTO);
        return Result.success();
    }


    @PostMapping(value = "/pageCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "藏品列表", notes = "藏品列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<DigitalCollectionVO> editCollection(@Valid @RequestBody PageDigitalCollectionRequest request) {
        Page p = digitalCollectionService.page(request.getFirstTitle(), request.getUserCreatorId(), request.getCatenaId(), request.getPageNo(), request.getPageSize(), request.getCollectionType(), request.getCollectionSearch());
        return PageResult.success(p);
    }


    @PostMapping(value = "/simpleList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "简单藏品列表", notes = "简单藏品列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<CollectionSimpleVO>> editCollection(@Valid @RequestBody ListDigitalCollectionRequest request) {
        return Result.successColl(digitalCollectionService.simpleList(request.getFirstTitle(), request.getUserCreatorId()), CollectionSimpleVO.class);
    }

    @PostMapping(value = "/simpleListByCollectionType", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "简单藏品列表按照分类", notes = "简单藏品列表按照分类", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<SimpleListByCollectionTypeVO> simpleListByCollectionType(@Valid @RequestBody SimpleListByCollectionTypeRequest request) {
        return PageResult.success(digitalCollectionService.simpleListByCollectionType(request.getCollectionType(), request.getCollectionName(), request.getPageNo(), request.getPageSize(), request.getDaoId()));
    }

    @PostMapping(value = "/simpleListByCollectionAll", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "简单藏品列表全部数据", notes = "简单藏品列表全部数据", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<SimpleListByCollectionTypeVO>> simpleListByCollectionAll(@RequestBody CollectionListRequest request) {
        return Result.success(digitalCollectionService.simpleListByCollectionAll(request.getTypeEnum()));
    }

    @PostMapping(value = "/seriesList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "系列", notes = "系列", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<SeriesListVO>> seriesList(@Valid @RequestBody SeriesListRequest seriesListRequest) {
        return Result.successColl(catenaInfoService.seriesList(seriesListRequest.getType()), SeriesListVO.class);
    }

    @PostMapping(value = "/level", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "等级", notes = "等级", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result level() {
        return Result.success(CollectionLevel.values());
    }

    @PostMapping(value = "/showLevel", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "展示等级", notes = "展示等级", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<ShowLevelVO>> showLevel() {
        List<ShowLevelVO> list = showLevelService.getAllShowLevel();
        return PageResult.success(list);
    }

    @PostMapping(value = "/getUserCreator", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "作者列表", notes = "等级", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<UserCreatorVO>> getUserCreator() {
        List<UserCreatorInfo> list = userCreatorInfoService.getUserCreator();
        return Result.successColl(list, UserCreatorVO.class);
    }

    /* @PostMapping(value="/getCollectionRule", produces = MediaType.APPLICATION_JSON_VALUE)
     @ApiOperation(value = "查看藏品合成规则",notes ="查看藏品合成规则",httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
     @SysMemberLogin
     public PageResult<CollectionRuleVO> getCollectionRule(@Valid @RequestBody CollectionRuleRequest request){
         Page<CollectionRuleVO> page=privilegeRuleService.getCollectionRule(request.getPageNo(),request.getPageSize(),request.getCollectionId());
         return PageResult.success(page);
     }


     @PostMapping(value="/addSynthesisCollectionRule", produces = MediaType.APPLICATION_JSON_VALUE)
     @ApiOperation(value = "设置藏品合成规则",notes ="设置藏品合成规则",httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
     @SysMemberLogin
     public Result addSynthesisCollectionRule(@Valid @RequestBody AddPrivilegeRuleRequest request){
         List<DigitalCollectionProductInfo> list= digitalCollectionProductInfoService.getByCollectionId(request.getPrivilegeCollectionId());
         List<PrivilegeRuleRequest> ruleList = request.getRuleList();
         if (list.size()>0){
             throw new GlobalRunTimeException(ErrorCode.GOODS_ON_SHELVES);
         }
         for (PrivilegeRuleRequest privilegeRuleRequest : ruleList) {
             DigitalCollection digitalCollection = (DigitalCollection) new DigitalCollection().selectById(privilegeRuleRequest.getConsumeCollectionId());
             List<PrivilegeRule> list1 =privilegeRuleService.getByCollectionIdAndConsumeId(request.getPrivilegeCollectionId(),privilegeRuleRequest.getConsumeCollectionId());
             if (list1.size()>0){
                 return Result.fail("消耗的藏品已存在请勿重复添加");
             }
             PrivilegeRule privilegeRule=new PrivilegeRule();
             privilegeRule.setCollectionId(request.getPrivilegeCollectionId());
             privilegeRule.setConsumeCollectionId(digitalCollection.getId());
             privilegeRule.setConsumeCollectionName(digitalCollection.getFirstTitle());
             privilegeRule.setConsumeCollectionLevel(digitalCollection.getLevel().getCode());
             privilegeRule.setConsumeCollectionNum(privilegeRuleRequest.getConsumeCollectionNum());
             privilegeRule.setIsDestroy(privilegeRuleRequest.getIsDestroy());
             privilegeRule.insert();
         }
         return Result.success();
     }

     @PostMapping(value="/updateCollectionRule", produces = MediaType.APPLICATION_JSON_VALUE)
     @ApiOperation(value = "修改合成规则",notes ="修改合成规则",httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
     @SysMemberLogin
     public Result updateCollectionRule(@Valid @RequestBody UpdateRuleRequest request){
         List<DigitalCollectionProductInfo> list= digitalCollectionProductInfoService.getByCollectionId(request.getId());
         if (list.size()>0){
             throw new GlobalRunTimeException(ErrorCode.GOODS_ON_SHELVES);
         }
         PrivilegeRule privilegeRule=new PrivilegeRule();
         privilegeRule.setId(request.getId());
         privilegeRule.setConsumeCollectionNum(request.getNumber());
         privilegeRule.setIsDestroy(request.getIsDestroy());
         privilegeRule.updateById();
         return Result.success();
     }*/
    @PostMapping(value = "/addPrivilege", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "添加权益", notes = "添加权益", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result addPrivilege(@Valid @RequestBody AddPrivilegeRequest request) {
        DigitalCollection digitalCollection = (DigitalCollection) new DigitalCollection().selectById(request.getCollectionId());
        List<Privilege> byCollectionId = privilegeService.getByCollectionId(request.getCollectionId());
        if (byCollectionId.size() > 0) {
            return Result.fail("该特权藏品已经添加了权益");
        }
        if (!digitalCollection.getIsPrivilege()) {
            return Result.fail("不是特权藏品不能设置特权藏品权益");
        }
        if (ObjectUtil.isNotNull(privilegeDao.getByLevel(request.getLevel()))) {
            return Result.fail("权益等级已存在");
        }
        if (ObjectUtil.isNotNull(privilegeDao.getByName(request.getName()))) {
            return Result.fail("权益名称已存在");
        }
        request.setTransferDiscount(request.getTransferDiscount().movePointLeft(1));
        BeanUtil.toBean(request, Privilege.class).insert();
        return Result.success();
    }

    @PostMapping(value = "/collectionPrivilege", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "查看藏品对应的权益", notes = "查看藏品对应的权益", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<CollectionPrivilegeVO> collectionPrivilege(@Valid @RequestBody CollectionPrivilegeRequest request) {
        Page<CollectionPrivilegeVO> page = privilegeService.collectionPrivilege(request.getPageNo(), request.getPageSize(), request.getId());
        return PageResult.success(page);
    }

    @PostMapping(value = "/editPrivilege", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "编辑权益", notes = "编辑权益", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result editPrivilege(@Valid @RequestBody EditPrivilegeRequest request) {
        request.setTransferDiscount(request.getTransferDiscount().movePointLeft(1));
        Privilege privilege = BeanUtil.toBean(request, Privilege.class);
        privilege.updateById();
        return Result.success();
    }


    @PostMapping(value = "/transferLog", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "藏品流转轨迹", notes = "编辑权益", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    @Transactional(rollbackFor = Exception.class)
    public PageResult<TransferLogDTO> transferLog(@Valid @RequestBody TransferLogRequest request) {
        return PageResult.success(userCollectionChainLogDao.getTransferLog(request.getFirstTitle(), request.getTransactionHash(), request.getAddress(), request.getToUserAddress(), request.getStartTime(), request.getEndTime(), request.getCollectionType(), request.getPageNo(), request.getPageSize()));
    }


    @PostMapping(value = "/collectionInitChain", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "藏品上链", notes = "藏品上链", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result collectionInitChain(@Valid @RequestBody IdRequest request) {

        //SysMember member = SysMemberPool.getMember();
        //if (member.getId().intValue() != 8) {
        //    return Result.fail("你的账户没有权限!");
        //}

        DigitalCollection collection = digitalCollectionDao.getById(request.getId());

        if (ObjectUtil.isNull(collection)) {
            return Result.fail("藏品不存在");
        }

        if (collection.getChainStatus() == CollectionChainStatusEnum.CHAIN_COMPLETED) {
            return Result.fail("藏品已上链完成");
        }

        if (StrUtil.isBlank(collection.getContractAddress())) {
            return Result.fail("必须先创建合约才能上链");
        }

        if (collection.getChainStatus() == CollectionChainStatusEnum.ON_THE_CHAIN) {
            return Result.fail("藏品上链中");
        }

        if (collection.getChainStatus() == CollectionChainStatusEnum.HISTORY_COLLECTION) {
            return Result.fail("历史藏品不能初始化上链");
        }

        String key = RedisKeyEnum.COLLECTION_INIT_LOCK.getKey() + collection.getId();
        RLock lock = redisson.getLock(key);
        try {
            boolean res = lock.tryLock(1, TimeUnit.SECONDS);
            if (res) {
                digitalCollectionService.collectionInitChain(collection);
            } else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("藏品上链中,请勿重复提交");
        } finally {
            lock.unlock();
        }

        return Result.success();
    }


    @ApiOperation(value = "根据Dao获取藏品列表", notes = "根据Dao获取藏品列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getCollectionListAccordingDao", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<CollectionListAccordingDaoVO> getCollectionListAccordingDao(@RequestBody CollectionListAccordingDaoDTO collectionListAccordingDaoDTO) {
        return PageResult.success(digitalCollectionService.getCollectionListAccordingDao(collectionListAccordingDaoDTO));
    }

    @ApiOperation(value = "获取自由市场的藏品列表", notes = "获取自由市场的藏品列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPageFreeMarketCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<AdminPageFreeMarketCollectionVO> getAdminPageFreeMarketCollection(@Valid @RequestBody AdminPageFreeMarketCollectionDTO adminPageFreeMarketCollectionDTO) {
        return PageResult.success(digitalCollectionService.getAdminPageFreeMarketCollection(adminPageFreeMarketCollectionDTO.getPageNo(), adminPageFreeMarketCollectionDTO.getPageSize(), adminPageFreeMarketCollectionDTO.getFirstTitle()));
    }

    @ApiOperation(value = "分页获取所有的藏品列表", notes = "分页获取所有的藏品列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPageCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<CollectionSimpleVO> getPageCollection(@Valid @RequestBody CollectionSimpleDTO collectionSimpleDTO) {
        return PageResult.success(digitalCollectionService.getPageCollection(collectionSimpleDTO.getPageNo(), collectionSimpleDTO.getPageSize(), collectionSimpleDTO.getFirstTitle()));
    }

    @ApiOperation(value = "分页获取二级的藏品列表", notes = "分页获取二级的藏品列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPageSecondaryMarketCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<CollectionSimpleVO> getPageSecondaryMarketCollection(@Valid @RequestBody PageRequest request) {
        return PageResult.success(digitalCollectionService.getPageSecondaryMarketCollection(request.getPageNo(), request.getPageSize()));
    }


    @ApiOperation(value = "获取版权藏品", notes = "获取版权藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/accessToCopyrightCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<AccessToCopyrightCollectionVO>> accessToCopyrightCollection(@Valid @RequestBody AccessToCopyrightCollectioDTO accessToCopyrightCollectioDTO) {
        return Result.success(digitalCollectionService.accessToCopyrightCollection(accessToCopyrightCollectioDTO));
    }

    @ApiOperation(value = "获取未绑定城市的藏品", notes = "获取未绑定城市的藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/collectionBindingCity", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<AccessToCopyrightCollectionVO>> collectionBindingCity(@Valid @RequestBody AccessToCopyrightCollectioDTO accessToCopyrightCollectioDTO) {
        return Result.success(digitalCollectionService.collectionBindingCity(accessToCopyrightCollectioDTO));
    }

    @ApiOperation(value = "根据类型分页获取藏品", notes = "根据类型分页获取藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getCollectionPageByCollectionType", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<CollectionSimpleVO> getCollectionPageByCollectionType(@Valid @RequestBody PageRequest request) {
        //上线钱修改为 获取除去版权之外的藏品
        return PageResult.success(digitalCollectionService.getCollectionPageByCollectionType(request.getPageNo(), request.getPageSize()));
    }


    @PostMapping(value = "/collectionSimpleList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "简单藏品列表", notes = "简单藏品列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<List<CollectionSimpleVO>> collectionSimpleList(@Valid @RequestBody ListDigitalCollectionRequest request) {
        return Result.successColl(digitalCollectionService.simpleList(request.getFirstTitle(), request.getUserCreatorId()), CollectionSimpleVO.class);
    }

    @PostMapping(value = "/getListByDigitalMarketType", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "藏品列表下拉框", notes = "藏品列表下拉框", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<List<DigitalCollectionMarketTypeVO>> findListByDigitalMarketType(@Valid @RequestBody DigitalCollectionMarketTypeDTO digitalCollectionMarketTypeDTO) {
        List<DigitalCollection> listByDigitalMarketType = digitalCollectionService.findListByDigitalMarketType(digitalCollectionMarketTypeDTO.getDigitalMarketTypeEnum());
        List<DigitalCollectionMarketTypeVO> digitalCollectionMarketTypeVOS = BeanUtil.copyToList(listByDigitalMarketType, DigitalCollectionMarketTypeVO.class);
        return Result.success(digitalCollectionMarketTypeVOS);
    }

}
